package com.kun.sync.writer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.kun.sync.util.DatabaseConnection;

/**
 * 批量操作
 * 
 * @author zjkorder (2018/1/30 9:40)
 */
public class BatchWriter {

	/**
	 * 数据库连接配置
	 */
	private String[] databaseConnectionConfig;

	/**
	 * 批量SQL
	 */
	private String sql;

	/**
	 * 数据库连接
	 */
	private Connection connection;

	private PreparedStatement preparedStatement;

	private int limit;

	private int index = 0;

	/**
	 * 批处理写入
	 * 
	 * @param databaseConnectionConfig 数据连接配置
	 * @param sql sql
	 * @param limit 每次提交数量
	 */
	public BatchWriter(String[] databaseConnectionConfig, String sql, int limit) throws SQLException {
		this.databaseConnectionConfig = databaseConnectionConfig;
		this.sql = sql;
		this.limit = limit;
		init();
	}

	/**
	 * 初始化
	 * 
	 * @throws SQLException 创建连接失败
	 */
	private void init() throws SQLException {
		connection = DatabaseConnection.createConnection(databaseConnectionConfig);
		connection.setAutoCommit(false);
		preparedStatement = connection.prepareStatement(sql);
	}

	/**
	 * 添加批处理
	 * 
	 * @param params 参数
	 * @param sqlType 参数类型
	 * @throws SQLException 添加异常
	 */
	public synchronized void addBatch(Object[] params, int... sqlType) throws SQLException {
		if (sqlType != null && sqlType.length != params.length) {
			throw new SQLException("sql type error!");
		}

		// 添加参数
		for (int i = 1; i <= params.length; i++) {
			if (sqlType != null) {
				preparedStatement.setObject(i, params[i - 1], sqlType[i - 1]);
			} else {
				preparedStatement.setObject(i, params[i - 1]);
			}

		}
		preparedStatement.addBatch();
		index++;

		// 提交事务
		if (index >= limit) {

			System.out.println("写入");
			preparedStatement.executeBatch();
			connection.commit();
			index = 0;
		}
	}

	/**
	 * 关闭数据库连接
	 * 
	 * @throws SQLException 关闭异常
	 */
	public void close() throws SQLException {
		// 提交事务
		preparedStatement.executeBatch();
		connection.commit();
		System.out.println("关闭");

		// 关闭数据
		DatabaseConnection.close(connection, preparedStatement, null);
	}
}
